home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / wide.c < prev   
Encoding:
C/C++ Source or Header  |  1988-11-24  |  5.3 KB  |  340 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2. static char rcsid[] = "$Header: wide.c,v 2.3 84/07/19 12:01:37 guido Exp $";
  3.  
  4. /*
  5.  * B editor -- Commands to make the focus larger and smaller in various ways.
  6.  */
  7.  
  8. #include "b.h"
  9. #include "bobj.h"
  10. #include "node.h"
  11. #include "supr.h"
  12. #include "gram.h"
  13.  
  14.  
  15. /*
  16.  * Widen -- make the focus larger.
  17.  */
  18.  
  19. Visible bool
  20. widen(ep)
  21.     register environ *ep;
  22. {
  23.     register node n;
  24.     register int sym;
  25.     register int ich;
  26.  
  27.     higher(ep);
  28.     grow(ep);
  29.  
  30.     n = tree(ep->focus);
  31.     sym = symbol(n);
  32.     if (ep->mode == VHOLE && (ep->s1&1))
  33.         ep->mode = FHOLE;
  34.         
  35.     switch (ep->mode) {
  36.  
  37.     case ATBEGIN:
  38.     case ATEND:
  39.         /* Shouldn't occur after grow(ep) */
  40.         ep->mode = WHOLE;
  41.         return Yes;
  42.  
  43.     case VHOLE:
  44.         if (ep->s2 >= lenitem(ep))
  45.             --ep->s2;
  46.         ep->mode = SUBRANGE;
  47.         ep->s3 = ep->s2;
  48.         return Yes;
  49.  
  50.     case FHOLE:
  51.         if (ep->s2 >= lenitem(ep)) {
  52.             if (ep->s2 > 0)
  53.                 --ep->s2;
  54.             else {
  55.                 leftvhole(ep);
  56.                 switch (ep->mode) {
  57.                 case ATBEGIN:
  58.                 case ATEND:
  59.                     ep->mode = WHOLE;
  60.                     return Yes;
  61.                 case VHOLE:
  62.                 case FHOLE:
  63.                     if (ep->s2 >= lenitem(ep)) {
  64.                         if (ep->s2 == 0) {
  65. #ifndef NDEBUG
  66.                             debug("[Desperate in widen]");
  67. #endif NDEBUG
  68.                             ep->mode = SUBSET;
  69.                             ep->s2 = ep->s1;
  70.                             return widen(ep);
  71.                         }
  72.                         --ep->s2;
  73.                     }
  74.                     ep->mode = SUBRANGE;
  75.                     ep->s3 = ep->s2;
  76.                     return Yes;
  77.                 }
  78.                 Abort();
  79.             }
  80.         }
  81.         ep->mode = SUBRANGE;
  82.         ep->s3 = ep->s2;
  83.         return Yes;
  84.  
  85.     case SUBRANGE:
  86.         ep->mode = SUBSET;
  87.         ep->s2 = ep->s1;
  88.         return Yes;
  89.             
  90.     case SUBSET:
  91.         if (!issublist(sym) || width(lastchild(n)) == 0) {
  92.             ep->mode = WHOLE;
  93.             return Yes;
  94.         }
  95.         if (ep->s2 < 2*nchildren(n)) {
  96.             ep->mode = SUBLIST;
  97.             ep->s3 = 1;
  98.             return Yes;
  99.         }
  100.         /* Fall through */
  101.     case SUBLIST:
  102.         for (;;) {
  103.             ich = ichild(ep->focus);
  104.             if (!up(&ep->focus)) {
  105.                 ep->mode = WHOLE;
  106.                 return Yes;
  107.             }
  108.             higher(ep);
  109.             n = tree(ep->focus);
  110.             if (ich != nchildren(n) || !samelevel(sym, symbol(n))) {
  111.                 ep->mode = SUBSET;
  112.                 ep->s1 = ep->s2 = 2*ich;
  113.                 return Yes;
  114.             }
  115.         }
  116.         /* Not reached */
  117.             
  118.     case WHOLE:
  119.         ich = ichild(ep->focus);
  120.         if (!up(&ep->focus))
  121.             return No;
  122.         n = tree(ep->focus);
  123.         if (issublist(symbol(n)) && ich < nchildren(n)) {
  124.             ep->mode = SUBLIST;
  125.             ep->s3 = 1;
  126.         }
  127.         return Yes;
  128.  
  129.     default:
  130.         Abort();
  131.         /* NOTREACHED */
  132.     }
  133.     /* Not reached */
  134. }
  135.  
  136.  
  137. /*
  138.  * Narrow -- make the focus smaller.
  139.  */
  140.  
  141. Visible bool
  142. narrow(ep)
  143.     register environ *ep;
  144. {
  145.     register node n;
  146.     register int sym;
  147.     register int nch;
  148.     register string repr;
  149.     
  150.     higher(ep);
  151.  
  152.     shrink(ep);
  153.     n = tree(ep->focus);
  154.     sym = symbol(n);
  155.  
  156.     switch (ep->mode) {
  157.         
  158.     case ATBEGIN:
  159.     case ATEND:
  160.     case VHOLE:
  161.     case FHOLE:
  162.         return No;
  163.     
  164.     case SUBRANGE:
  165.         if (ep->s3 > ep->s2)
  166.             ep->s3 = ep->s2;
  167.         else
  168.             ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
  169.         return Yes;
  170.         
  171.     case SUBSET:
  172.         if (ep->s1 <= 2) {
  173.             nch = nchildren(n);    
  174.             if (ep->s2 >= 2*nch && issublist(symbol(n))) {
  175.                 if (ep->s1 <= 1) {
  176.                     ep->s2 = 2*nch - 1;
  177.                     return Yes;
  178.                 }
  179.                 repr = noderepr(n)[0];
  180.                 if (!Fw_positive(repr)) {
  181.                     ep->s2 = 2*nch - 1;
  182.                     return Yes;
  183.                 }
  184.             }
  185.         }
  186.         ep->s2 = ep->s1;
  187.         return Yes;
  188.         
  189.     case SUBLIST:
  190.         Assert(ep->s3 > 1);
  191.         ep->s3 = 1;
  192.         return Yes;
  193.         
  194.     case WHOLE:
  195.         Assert(sym == Hole || sym == Optional);
  196.         return No;
  197.         
  198.     default:
  199.         Abort();
  200.         /* NOTREACHED */
  201.     }
  202. }
  203.  
  204.  
  205. Visible bool
  206. extend(ep)
  207.     register environ *ep;
  208. {
  209.     register node n;
  210.     register int i;
  211.     register int len;
  212.     register int s1save;
  213.  
  214.     grow(ep);
  215.     higher(ep);
  216.     switch (ep->mode) {
  217.  
  218.     case VHOLE:
  219.     case FHOLE:
  220.     case ATBEGIN:
  221.     case ATEND:
  222.         return widen(ep);
  223.  
  224.     case SUBRANGE:
  225.         len = lenitem(ep);
  226.         if (ep->s3 < len-1)
  227.             ++ep->s3;
  228.         else if (ep->s2 > 0)
  229.             --ep->s2;
  230.         else {
  231.             ep->mode = SUBSET;
  232.             ep->s2 = ep->s1;
  233.             return extend(ep); /* Recursion! */
  234.         }
  235.         return Yes;
  236.  
  237.     case SUBSET:
  238.         s1save = ep->s1;
  239.         ep->s1 = ep->s2;
  240.         if (nextnnitem(ep)) {
  241.             ep->s2 = ep->s1;
  242.             ep->s1 = s1save;
  243.         }
  244.         else {
  245.             ep->s1 = s1save;
  246.             prevnnitem(ep) || Abort();
  247.         }
  248.         return Yes;
  249.  
  250.     case WHOLE:
  251.         return up(&ep->focus);
  252.  
  253.     case SUBLIST:
  254.         n = tree(ep->focus);
  255.         for (i = ep->s3; i > 1; --i)
  256.             n = lastchild(n);
  257.         if (samelevel(symbol(n), symbol(lastchild(n)))) {
  258.             ++ep->s3;
  259.             return Yes;
  260.         }
  261.         ep->mode = WHOLE;
  262.         if (symbol(lastchild(n)) != Optional)
  263.             return Yes;
  264.         return extend(ep); /* Recursion! */
  265.  
  266.     default:
  267.         Abort();
  268.         /* NOTREACHED */
  269.     }
  270. }
  271.  
  272.  
  273. /*
  274.  * Right-Narrow -- make the focus smaller, going to the last item of a list.
  275.  */
  276.  
  277. Visible bool
  278. rnarrow(ep)
  279.     register environ *ep;
  280. {
  281.     register node n;
  282.     register int i;
  283.     register int sym;
  284.     
  285.     higher(ep);
  286.  
  287.     shrink(ep);
  288.     n = tree(ep->focus);
  289.     sym = symbol(n);
  290.     if (sym == Optional || sym == Hole)
  291.         return No;
  292.  
  293.     switch (ep->mode) {
  294.         
  295.     case ATBEGIN:
  296.     case ATEND:
  297.     case VHOLE:
  298.     case FHOLE:
  299.         return No;
  300.     
  301.     case SUBRANGE:
  302.         if (ep->s3 > ep->s2)
  303.             ep->s2 = ep->s3;
  304.         else {
  305.             ++ep->s2;
  306.             ep->mode = (ep->s1&1) ? FHOLE : VHOLE;
  307.         }
  308.         return Yes;
  309.         
  310.     case SUBSET:
  311.         if (issublist(sym) && ep->s2 >= 2*nchildren(n)) {
  312.             do {
  313.                 sym = symbol(n);
  314.                 s_downrite(ep);
  315.                 n = tree(ep->focus);
  316.             } while (samelevel(sym, symbol(n))
  317.                 && width(lastchild(n)) != 0);
  318.             ep->mode = WHOLE;
  319.             return Yes;
  320.         }
  321.         ep->s1 = ep->s2;
  322.         return Yes;
  323.         
  324.     case SUBLIST:
  325.         Assert(ep->s3 > 1);
  326.         for (i = ep->s3; i > 1; --i)
  327.             s_downi(ep, nchildren(tree(ep->focus)));
  328.         ep->s3 = 1;
  329.         return Yes;
  330.         
  331.     case WHOLE:
  332.         Assert(sym == Hole || sym == Optional);
  333.         return No;
  334.         
  335.     default:
  336.         Abort();
  337.         /* NOTREACHED */
  338.     }
  339. }
  340.